package com.heaven1949.tmall.common.web.filter;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.heaven1949.tmall.common.core.constants.CommonConstant;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;

/**
 * LogbackMdcFilter
 *
 * @author PC3
 */
@Slf4j
@Component
public class LogbackMdcFilter implements Filter {

    /**
     * 拦截并打印日志的URL
     */
    private final static String PRINT_LOG_URL_PATTERN = "/api/**";
    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        String requestURI = req.getRequestURI();
        if (antPathMatcher.match(PRINT_LOG_URL_PATTERN, requestURI)) {
            long start = System.currentTimeMillis();
            RequestInfo reqInfo = buildRequestInfo(request);
            String uuid = UUID.randomUUID().toString();
            MDC.put(CommonConstant.REQUEST_KEY, uuid);
            log.info(">>>>>>>>>> 请求信息: [{}]", JSONUtil.toJsonStr(reqInfo));
            chain.doFilter(request, response);
            log.info("<<<<<<<<<< 处理结束, 用时：[{}]ms", (System.currentTimeMillis() - start));
            MDC.remove(CommonConstant.REQUEST_KEY);
        } else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void init(FilterConfig arg0) {
    }

    private RequestInfo buildRequestInfo(ServletRequest request) {
        HttpServletRequest req = (HttpServletRequest) request;
        RequestInfo reqInfo = new RequestInfo();
        reqInfo.setSession(req.getSession().getId());
        reqInfo.setRemoteHost(req.getRemoteHost());
        reqInfo.setRequestURI(req.getRequestURI());
        reqInfo.setRequestURL(req.getRequestURL().toString());
        if (!StrUtil.equalsIgnoreCase(HttpMethod.GET.name(), req.getMethod())) {
            reqInfo.setQueryString(req.getQueryString());
        } else {
            Map<String, String[]> parameterMap = request.getParameterMap();
            reqInfo.setQueryString(JSONUtil.toJsonStr(parameterMap));
        }
        reqInfo.setUserAgent(req.getHeader("User-Agent"));
        reqInfo.setForwarded(req.getHeader("X-Forwarded-For"));
        reqInfo.setRemoteIp(req.getRemoteAddr());
        reqInfo.setMethod(req.getMethod());
        return reqInfo;
    }

    @Setter
    @Getter
    class RequestInfo {
        private String requestURL;
        private String requestURI;
        private String queryString;
        private String method;
        private String remoteHost;
        private String remoteIp;
        private String session;
        private String userAgent;
        private String Forwarded;
    }

}